import ChatWsClass from "../ttsutil/chatws";
import ttsWsClass from "../ttsutil/ttsws";
import sttWsClass from "../ttsutil/sttws";

import emitter from '@/mitt/emitter.js'
import { MetahumanEventType } from '@/mitt/MetahumanEventType.js'




class metaClass
{
  constructor(appkey,sttConfig , chatConfig , ttsConfig)
  {
    this.appkey = appkey;
    this.sttWs = new sttWsClass(sttConfig.url,appkey);

    this.chatConfig = {
      url : chatConfig.url,
      characterId :chatConfig.characterId,
      userId :chatConfig.userId ? chatConfig.userId : null, 
    }

    this.ttsConfig = {
      url : ttsConfig.url,
      appkey : appkey,
      voice : ttsConfig.voice,
      apiType : ttsConfig.apiType,
      volume : ttsConfig.volume ? ttsConfig.volume  : 50,
      speech_rate : ttsConfig.speech_rate  ? ttsConfig.speech_rate  : 0,
      pitch_rate : ttsConfig.pitch_rate ? ttsConfig.pitch_rate  : 0,
    }


    this._chatWs = null;
    this._ttsWs = null;
    this._audios = [];
    this._isPlaying = false;

    this.init();
  }

  init()
  {
    this.sttWs.OnCompleted = this.ttsOnCompleted.bind(this);
  }


  startRecording()
  {
    this.sttWs.start();
  }


  stopRecording()
  {
    console.log("stop recording");
    this.sttWs.stop();
  }

  ttsOnCompleted(content)
  {
    this.sendChatMessage(content);
  }

  sendChatMessage(content)
  {

    console.log(content);
    // 发送chat信息，获取大模型返回内容
    let chatWs = new ChatWsClass(this.chatConfig.url,this.chatConfig.characterId,content,this.chatConfig.userId)
    chatWs.createAudio = this.createAudio.bind(this);

    // 自动销毁
    chatWs.ws.onClose = ()=>{
      chatWs = null;
    }

  }


  createAudio(msg)
  {
    console.log(msg);
    if(!msg) return false;
    let ttsWs = new ttsWsClass(
      this.ttsConfig.url,
      msg,
      this.appkey,
      this.ttsConfig.voice,
      this.ttsConfig.apiType,
      this.ttsConfig.volume,
      this.ttsConfig.speech_rate,
      this.ttsConfig.pitch_rate,
    )
    ttsWs.createAudioSuccess = this.createAudioSuccess.bind(this);

    // 自动销毁
    ttsWs.ws.onClose = ()=>{
      ttsWs = null;
    };
  }




  createAudioSuccess(audioUrl,msg,phoneme_list)
  {
    let audioObj = {
      url : audioUrl,
      msg : msg,
      phoneme_list : phoneme_list
    };
    this._audios.push(audioObj);

    if(!this._isPlaying)
    {
      this.playAudio();
    }
  }


  // 短暂记忆 后台处理 * 
  playAudio()
  {
    const _self = this;
    if(this._isPlaying || this._audios.length <= 0) return;
    _self._isPlaying = true;
    let audioObj = this._audios.shift();

    let audio = new Audio(audioObj.url); 
    audio.crossOrigin = 'anonymous';
    let audioCtx = new AudioContext();
    let source = audioCtx.createMediaElementSource(audio);
    // 链接到 destination
    source.connect(audioCtx.destination);
    // 创建 ScriptProcessorNode
    let processor = audioCtx.createScriptProcessor(256);
    // 链接到 destination
    processor.connect(audioCtx.destination);


    const handleAudioProcess = () => {
      if(audio.currentTime == audio.duration)
      {
        processor.removeEventListener('audioprocess', handleAudioProcess);
        this._isPlaying = false;

        if( _self._audios.length >= 1)
        { 
          _self.playAudio() 
        }
        
        // 内部销毁
        processor.disconnect();
        source.disconnect();
        audio = null;
        audioCtx = null;
        processor = null;
        source = null;
      }else{
        const  currentAudioTime = audio.currentTime * 1000;
        const progress = audio.currentTime / audio.duration;
        let strLen = Math.round(progress * audioObj.msg.length);
        for (let i = 0; i < audioObj.phoneme_list.length; i++) 
        {
          let sync = audioObj.phoneme_list[i];
          if(currentAudioTime >= sync.begin_time && currentAudioTime < sync.end_time)
          {
            // console.log(sync.phoneme)
            // emitter.emit(MetahumanEventType.LipSyncAnimation,sync.phoneme);
            break;
          }
        }
      }
    }
  
    // 监听 audioProcess
    processor.addEventListener('audioprocess', handleAudioProcess);

    audio.play();
  }


}




export default metaClass;